package iot

import (
	"errors"
	"gorm.io/gorm"
	"iot-base/auth/types"
	"iot-base/auth/utils"
	"iot-base/common/dbobj"
)

type (
	Thing      dbobj.Thing
	ThingModel struct {
		db *gorm.DB
	}
)

func NewThingModel(db *gorm.DB) *ThingModel {
	return &ThingModel{
		db,
	}
}

func (t *ThingModel) Insert(param *Thing) error {
	if param.UID == "" {
		param.UID = utils.AutoID()
	}
	return t.db.Create(param).Error
}

func (t *ThingModel) WhereInId(ids []string) ([]Thing, error) {
	var things []Thing
	err := t.db.Model(&Thing{}).Where("uid in ?", ids).Find(&things).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return things, nil
	}
	return things, err
}

func (t *ThingModel) Update(param Thing) error {
	return t.db.Where("uid = ?", param.UID).Save(param).Error
}

func (t *ThingModel) FindStationsThing(stationId string, isVideo bool) ([]Thing, error) {
	things := make([]Thing, 0, 1)
	dbSession := t.db.Model(&Thing{})
	dbSession.Joins("JOIN thing_stations ON thing_stations.thing_id = things.uid AND thing_stations.station_id = ?", stationId)
	if isVideo {
		dbSession.Joins("JOIN t_models ON t_models.uid = things.model_id AND t_models.has_stream = ?", true)
	}
	err := dbSession.Find(&things).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return things, nil
	}
	return things, err
}

func (t *ThingModel) FindVideoThing() ([]Thing, error) {
	things := make([]Thing, 0, 1)
	dbSession := t.db.Model(&Thing{})
	//dbSession.Joins("JOIN thing_stations ON thing_stations.thing_id = things.uid")
	dbSession.Joins("JOIN t_models ON t_models.uid = things.model_id AND t_models.has_stream = ?", true)
	err := dbSession.Find(&things).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return things, nil
	}
	return things, err
}

func (t *ThingModel) GetThingById(id string) (Thing, error) {
	var thingInfo Thing
	dbSession := t.db.Model(&Thing{})
	dbSession.Where("uid = ?", id)
	err := dbSession.First(&thingInfo).Error
	return thingInfo, err
}

func (t *ThingModel) QueryMgThingCount(stationsId string) (int64, error) {
	var total int64
	sql := "SELECT count(1) as total " +
		"FROM things " +
		"JOIN thing_stations ON thing_stations.thing_id = things.uid " +
		"left JOIN thing_states ON thing_states.thing_id = things.uid JOIN t_models ON t_models.uid=things.model_id " +
		"left JOIN thing_maintain_infos ON thing_maintain_infos.thing_id = things.uid " +
		"WHERE thing_stations.station_id = ?"
	tx := t.db.Raw(sql, stationsId).First(&total)
	err := tx.Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return total, nil
	}
	return total, nil
}

func (t *ThingModel) QueryMgThingList(stationsId string, page, size int) ([]types.RespMgGetThing, error) {
	var result []types.RespMgGetThing
	sql := " SELECT things.*,thing_stations.sno,thing_states.state,thing_states.state," +
		"t_models.s_name as model_name,t_models.catalog_id,thing_maintain_infos.used_time," +
		"thing_maintain_infos.buy_time,thing_maintain_infos.create_time ,thing_maintain_infos.first_online_time as first_online_time " +
		"FROM things JOIN thing_stations ON thing_stations.thing_id = things.uid left " +
		"JOIN thing_states ON thing_states.thing_id = things.uid " +
		"JOIN t_models ON t_models.uid=things.model_id " +
		"left JOIN thing_maintain_infos ON thing_maintain_infos.thing_id = things.uid " +
		"WHERE thing_stations.station_id = ?  ORDER BY things.uid limit ? Offset ?"
	tx := t.db.Raw(sql, stationsId, size, (page-1)*size).Find(&result)
	err := tx.Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return result, nil
	}
	return append([]types.RespMgGetThing{}, result...), nil
}

func (t *ThingModel) QuerySelectEdge(modelId string, data *[]types.RespSelectEdge) error {
	err := t.db.Model(&Thing{}).Select("uid as id,s_name as name").Where("model_id = ?", modelId).Find(data).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return nil
	}
	return err
}

func (t *ThingModel) DeleteMap(param map[string]interface{}) error {
	return t.db.Where(param).Delete(&Thing{}).Error
}
